/*
 *  simulation.h
 *  EPPI-0.0
 *
 *  Created by Juan Carlos Garcia Orden on 15/11/07.
 *
 */

#ifndef _simulation_h_
#define _simulation_h_

#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <time.h>
#include <unistd.h>
#include <sys/stat.h>

using namespace std;

#include "process.h"
#include "history.h"

#include "GEOMETRY/surface.h"
#include "GEOMETRY/surfacemesh.h"
#include "GEOMETRY/surfacesphere.h"
#include "GEOMETRY/surfaceellipsoid.h"
#include "GEOMETRY/surfacesuperellipsoid.h"
#include "GEOMETRY/surfaceplane.h"
#include "GEOMETRY/surfacebox.h"

#include "ANALYSES/analysis.h"
#include "MATERIALS/material.h"
#include "MATERIALS/elasticlog.h"
#include "MATERIALS/elasticlinear.h"
#include "MATERIALS/elasticlog3d.h"
#include "MATERIALS/ogden.h"
#include "MATERIALS/svk.h"
#include "MATERIALS/neohooke.h"
#include "MATERIALS/mooneyrivlin.h"
#include "MATERIALS/composite.h"
#include "MATERIALS/viscoelastic.h"
#include "MATERIALS/thermoelastic.h"
#include "MATERIALS/damage.h"
#include "ANALYSES/static.h"
#include "ANALYSES/directdynamic.h"

extern int rankk;

class Process;
//class Solver;

class Simulation
{
public:
	int nProc;				/** Total number of processes */
	int nSys;				/** Total number of systems */
 	ifstream ini;
	string keyword;
	char inputFileName[30];
	char title[100];
	int dimension;
	int mode;
	int vecType;			/** Vector type for LMX */
	int matType;			/** Matrix type for LMX */
	vector<Process*> vProcesses;					/** Vector of processes */
	Process* lProcess;
	map<string, int, less<string> > mSysProc;	/** System name - process number */
	vector<Analysis*> vAnalyses;				/** Vector of analyses */
	Analysis* currentAnalysis;					/** Current analysis */
	map<string,Material*,less<string> > mMaterials;	/** Map of materials */
	map<string,Surface*,less<string> > mSurfaces;	/** Map of surfaces */
	time_t rawtime;
	vector<string> vDofNames;						/** Names of points with requested output */
	vector<string> vStressNames;						/** Names of points with requested output */
	string graphicsFormat;							/** Name of the format for graphics */
	string graphicsPath;                           /** Path of the graphics */
	double graphicsStep;
	ofstream fGraphTot;
	ofstream fEner;
	ofstream fTemp;
	ofstream fEntropy;
	ofstream fAM;
	ofstream fCon;
	ofstream fPProj;
	bool printPosFlag;
	bool printEnerFlag;
	bool printIterFlag;
	bool printTempFlag;
	bool printEntropyFlag;
	bool printAMFlag;
	bool printConFlag;
	bool printPProjFlag;
	bool printStressFlag;
	bool plotDispFlag;
	bool plotProcFlag;
	bool plotStressFlag;
	char outEnerFile[300];
	char outTempFile[300];
	char outEntropyFile[300];
	char outAMFile[300];
	char outConFile[300];
	char outPProjFile[300];
	double Ekin;
	double Epot;
	double Econ;
    double Eext;
	double Eamb;
    double Dint;
	double Entropy;
	double EntropyAmb;
	vector<string> vTempNames;	/** Names of bodies/joints with requested temperature output */
	vector<double> AM;
	vector<double> vCon;
	bool symmFlag;				// Only for interfaces. More general use TO BE DONE
	map<string,History*,less<string> > mHistories;
//	vector<History*> vHistory;
	
	
public:
	Simulation();
	Simulation(char*);
	~Simulation();

	void readGeneral();			/** Read general options and systems from input file */
	void readSystems();			/** Read general options and systems from input file */
	void readAnalyses();		/** Read analysis from input file */
	void sendSysProc();			/** Sends table system-procNumber AND procNumber-procPointer to every process */
	void readMaterials();		/** Read materials */
	void readPost();			/** Read postprocess options */
	void initializeProc();		/** Initialize processes */
	void initializeAnalysis();	/** Initialize the current analysis to every process */
	void checkVelNeeded();		/** Check if velocity vector is needed */
	void sendMaterials();		/** Send all materials to all processes */
	void readSurfaces();
	void sendSurfaces();		/** Send all surfaces to all processes */
	
	/** For a system name, provides the pointer to the process */
	Process* getProcFromSys(const string &sysName) { return( (vProcesses[mSysProc[sysName]]) ); }
	void reportContentFile();
	void eraseProcesses();		/** Erase processes that do not match the rankk */
	void setOutput();				/** Create file and Set pointers to points with requested output, at local process */
	void setGravity(double&, int&);			/** Set gravity force to all bodies, in all processes */
	void createTotalGraphOutFile();
	void collectEner(void);
	void collectEntropy(void);
	void collectAM(void);
	void collectCon(void);
	void createFileEner(void);
	void createFileEntropy(void);
	void createFileAM(void);
	void createFileCon(void);
	void createFilePProj(void);
	void writeFileEner(double&);
	void writeFileEntropy(double&);
	void writeFileAM(double&);
	void writeFileCon(double&);
	void writeFilePProj(double&, double&);
	void closeFileEner(void);
	void closeFileEntropy(void);
	void closeFileAM(void);
	void closeFileCon(void);
	void closeFilePProj(void);
	void setProcTemperature(double&);
	void createHistory(char*);
	void createHistory(double&);
	
	/** Friend functions */
	friend string getStringHead(const string& str);
	friend void setZero(vector<double>& v);

   /*   protected:
        void COMM_WORLD(double* Epot, double* Epot, int arg3, MPI::DOUBLE arg4, MPI::SUM arg5);
        private:
        void COMM_WORLD(double* Epot, double* Epot, int arg3, MPI::DOUBLE arg4, MPI::SUM arg5);*/
};

#endif
